package com.uhu.tag.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.uhu.common.UtagConstant;
import com.uhu.dto.req.TagCategorySaveReqDTO;
import com.uhu.dto.req.TagCategoryUpdateReqDTO;
import com.uhu.dto.res.TagCategoryQueryResDTO;
import com.uhu.exception.BusinessException;
import com.uhu.redis.RedisKeyConstant;
import com.uhu.tag.dao.TagCategoryMapper;
import com.uhu.tag.entity.TagCategory;
import com.uhu.tag.entity.TagGroup;
import com.uhu.tag.service.ITagCategoryService;
import com.uhu.tag.service.ITagGroupService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author liujunjie
 * @description
 * @create 2023-06-01 16:31
 **/
@Slf4j
@Service
public class TagCategoryServiceImpl extends ServiceImpl<TagCategoryMapper, TagCategory> implements ITagCategoryService {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ITagGroupService iTagGroupService;

    @Override
    public List<TagCategoryQueryResDTO> queryTagCategorySelect() {
        List<TagCategory> list = list(new QueryWrapper<TagCategory>()
                .orderByAsc("sort_id")
        );

        return BeanUtil.copyToList(list, TagCategoryQueryResDTO.class);
    }

    @Override
    public void saveTagCategory(TagCategorySaveReqDTO tagCategorySaveReqDTO) {
        RLock rLock = redissonClient.getLock(RedisKeyConstant.TAG_CATEGORY_EDIT_LOCK);
        if (!rLock.tryLock()) {
            throw new BusinessException(UtagConstant.GET_LOCK_FAIL);
        }

        try {
            TagCategory tagCategory = getOne(new QueryWrapper<TagCategory>()
                    .orderByAsc("sort_id").last("limit 1"));
            Integer lastSortId = 0;
            if (tagCategory != null) {
                lastSortId = tagCategory.getSortId() + 1;
            }
            TagCategory saveTagCategory = BeanUtil.copyProperties(tagCategorySaveReqDTO, TagCategory.class);
            saveTagCategory.setSortId(lastSortId);
            saveOrUpdate(saveTagCategory);
        } finally {
            rLock.unlock();
        }
    }

    @Override
    public void updateTagCategory(TagCategoryUpdateReqDTO tagCategoryUpdateReqDTO) {
        RLock rLock = redissonClient.getLock(RedisKeyConstant.TAG_CATEGORY_EDIT_LOCK);
        if (!rLock.tryLock()) {
            throw new BusinessException(UtagConstant.GET_LOCK_FAIL);
        }

        try {
            long count = count(new QueryWrapper<TagCategory>().eq("tag_category_id", tagCategoryUpdateReqDTO.getTagCategoryId()));
            if (count < 1) {
                throw new BusinessException("标签大类不存在");
            }
            saveOrUpdate(BeanUtil.copyProperties(tagCategoryUpdateReqDTO, TagCategory.class));
        } finally {
            rLock.unlock();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sortTagCategory(Long[] ids) {
        RLock rLock = redissonClient.getLock(RedisKeyConstant.TAG_CATEGORY_EDIT_LOCK);
        if (!rLock.tryLock()) {
            throw new BusinessException(UtagConstant.GET_LOCK_FAIL);
        }

        try {
            Long size = count(new QueryWrapper<TagCategory>()
                    .in("tag_category_id", ids)
            );
            if (size != ids.length) {
                log.error("sortTagCategory ids.length != database.size, please check it");
                throw new BusinessException(UtagConstant.SYSTEM_ERROR);
            }

            for (int i = 0; i < ids.length; i++) {
                TagCategory tagCategory = new TagCategory();
                tagCategory.setTagCategoryId(ids[i]);
                tagCategory.setSortId(i);
                updateById(tagCategory);
            }
        } finally {
            rLock.unlock();
        }
    }

    @Override
    public void deleteTagCategory(Long tagCategoryId) {
        RLock rLock = redissonClient.getLock(RedisKeyConstant.TAG_CATEGORY_EDIT_LOCK);
        if (!rLock.tryLock()) {
            throw new BusinessException(UtagConstant.GET_LOCK_FAIL);
        }

        try {
            Long size = count(new QueryWrapper<TagCategory>()
                    .eq("tag_category_id", tagCategoryId)
                    .last("limit 1")
            );
            if (size < 1) {
                log.error("deleteTagCategory tagCategoryId = {} not found", tagCategoryId);
                throw new BusinessException(UtagConstant.SYSTEM_ERROR);
            }

            Long childSize = iTagGroupService.count(new QueryWrapper<TagGroup>()
                    .eq("tag_category_id", tagCategoryId)
                    .last("limit 1")
            );
            if (childSize > 0) {
                throw new BusinessException("当前大类下已存在标签组，无法删除！！！");
            }

            removeById(tagCategoryId);
        } finally {
            rLock.unlock();
        }
    }
}
